package com.kexio.security.service.impl;

import com.kexio.common.dto.PageRequest;
import com.kexio.common.dto.PageResponse;
import com.kexio.dynamic.datasource.annotation.DS;
import com.kexio.dynamic.datasource.annotation.Master;
import com.kexio.dynamic.datasource.annotation.Slave;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Caching;
import com.kexio.security.domain.User;
import com.kexio.security.domain.enums.UserStatus;
import com.kexio.security.dto.UserDTO;
import com.kexio.security.dto.UserRequest;
import com.kexio.security.service.UserRepository;
import com.kexio.security.service.UserRoleRepository;
import com.kexio.security.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户业务服务实现类
 * 
 * @author kexio
 */
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    private final UserRepository userRepository;
    private final UserRoleRepository userRoleRepository;

    public UserServiceImpl(UserRepository userRepository, UserRoleRepository userRoleRepository) {
        this.userRepository = userRepository;
        this.userRoleRepository = userRoleRepository;
    }

    @Override
    @Transactional
    public UserDTO createUser(UserRequest request) {
        log.info("开始创建用户: {}", request.getUsername());
        
        // 验证用户名唯一性
        if (existsByUsername(request.getUsername(), null)) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 验证邮箱唯一性
        if (request.getEmail() != null && existsByEmail(request.getEmail(), null)) {
            throw new RuntimeException("邮箱已被使用");
        }
        
        // 验证手机号唯一性
        if (request.getPhone() != null && existsByPhone(request.getPhone(), null)) {
            throw new RuntimeException("手机号已被使用");
        }

        // 创建用户实体
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(encodePassword(request.getPassword())); // 需要密码加密
        user.setNickname(request.getNickname());
        user.setRealName(request.getRealName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setAvatar(request.getAvatar());
        user.setStatus(request.getStatus() != null ? request.getStatus() : UserStatus.ACTIVE.getCode());
        user.setDeptId(request.getDeptId());
        user.setPositionId(request.getPositionId());
        user.setRemark(request.getRemark());
        user.setLoginCount(0);

        // 保存用户
        user = userRepository.save(user);
        
        log.info("用户创建成功: {} (ID: {})", user.getUsername(), user.getId());
        // 将新创建的用户放入缓存
        UserDTO userDTO = UserDTO.fromEntity(user);
        return userDTO;
    }

    @Override
    @Transactional
    public UserDTO updateUser(UserRequest request) {
        log.info("开始更新用户: {}", request.getId());
        
        User user = userRepository.findById(request.getId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 验证用户名唯一性（排除当前用户）
        if (request.getUsername() != null && !request.getUsername().equals(user.getUsername())) {
            if (existsByUsername(request.getUsername(), request.getId())) {
                throw new RuntimeException("用户名已存在");
            }
            user.setUsername(request.getUsername());
        }

        // 验证邮箱唯一性（排除当前用户）
        if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
            if (existsByEmail(request.getEmail(), request.getId())) {
                throw new RuntimeException("邮箱已被使用");
            }
            user.setEmail(request.getEmail());
        }

        // 验证手机号唯一性（排除当前用户）
        if (request.getPhone() != null && !request.getPhone().equals(user.getPhone())) {
            if (existsByPhone(request.getPhone(), request.getId())) {
                throw new RuntimeException("手机号已被使用");
            }
            user.setPhone(request.getPhone());
        }

        // 更新其他字段
        if (request.getNickname() != null) user.setNickname(request.getNickname());
        if (request.getRealName() != null) user.setRealName(request.getRealName());
        if (request.getAvatar() != null) user.setAvatar(request.getAvatar());
        if (request.getStatus() != null) user.setStatus(request.getStatus());
        if (request.getDeptId() != null) user.setDeptId(request.getDeptId());
        if (request.getPositionId() != null) user.setPositionId(request.getPositionId());
        if (request.getRemark() != null) user.setRemark(request.getRemark());

        // 保存用户
        user = userRepository.save(user);
        
        log.info("用户更新成功: {} (ID: {})", user.getUsername(), user.getId());
        return UserDTO.fromEntity(user);
    }

    @Override
    @Slave // 查询操作使用从库
    @Cacheable(value = "users", key = "#id", unless = "#result == null")
    public UserDTO getUserById(Long id) {
        return userRepository.findById(id)
                .map(UserDTO::fromEntity)
                .orElse(null);
    }

    @Override
    @Slave // 查询操作使用从库
    @Cacheable(value = "users", key = "'username:' + #username", unless = "#result == null")
    public UserDTO getUserByUsername(String username) {
        return userRepository.findByUsername(username)
                .map(UserDTO::fromEntity)
                .orElse(null);
    }

    @Override
    public PageResponse<UserDTO> queryUsers(UserRequest request, PageRequest pageRequest) {
        PageResponse<User> userPage = userRepository.findPage(request, pageRequest);
        
        // 转换为DTO
        List<UserDTO> userDTOs = userPage.getRecords().stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
        
        return new PageResponse<>(userDTOs, userPage.getPage(), userPage.getSize(), userPage.getTotal());
    }

    @Override
    public List<UserDTO> getUsersByDeptId(Long deptId) {
        return userRepository.findByDeptId(deptId).stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserDTO> getUsersByRoleId(Long roleId) {
        return userRepository.findByRoleId(roleId).stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public boolean enableUser(Long id) {
        return updateUserStatus(id, UserStatus.ACTIVE.getCode());
    }

    @Override
    @Transactional
    public boolean disableUser(Long id) {
        return updateUserStatus(id, UserStatus.DISABLED.getCode());
    }

    private boolean updateUserStatus(Long id, Integer status) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            return false;
        }
        
        user.setStatus(status);
        userRepository.save(user);
        return true;
    }

    @Override
    @Transactional
    public boolean resetPassword(Long id, String newPassword) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            return false;
        }
        
        user.setPassword(encodePassword(newPassword));
        userRepository.save(user);
        log.info("用户{}密码重置成功", user.getUsername());
        return true;
    }

    @Override
    @Transactional
    public boolean changePassword(Long id, String oldPassword, String newPassword) {
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            return false;
        }
        
        // 验证旧密码
        if (!validateEncodedPassword(oldPassword, user.getPassword())) {
            return false;
        }
        
        user.setPassword(encodePassword(newPassword));
        userRepository.save(user);
        log.info("用户{}密码修改成功", user.getUsername());
        return true;
    }

    @Override
    @Transactional
    public boolean deleteUser(Long id) {
        // 删除用户角色关联
        userRoleRepository.deleteByUserId(id);
        
        // 删除用户
        int rows = userRepository.deleteById(id);
        return rows > 0;
    }

    @Override
    @Transactional
    public int deleteUsers(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        
        // 批量删除用户角色关联
        userRoleRepository.deleteByUserIds(ids);
        
        // 批量删除用户
        return userRepository.deleteByIds(ids);
    }

    @Override
    @Transactional
    public boolean assignRoles(Long userId, List<Long> roleIds) {
        // TODO: 实现角色分配逻辑
        log.info("为用户{}分配角色: {}", userId, roleIds);
        return true;
    }

    @Override
    @Transactional
    public boolean removeRoles(Long userId, List<Long> roleIds) {
        // TODO: 实现角色移除逻辑
        log.info("为用户{}移除角色: {}", userId, roleIds);
        return true;
    }

    @Override
    public List<Long> getUserRoles(Long userId) {
        // TODO: 实现获取用户角色逻辑
        return java.util.Collections.emptyList();
    }

    @Override
    @Transactional
    public boolean updateLastLoginInfo(Long userId, String loginIp) {
        int rows = userRepository.updateLastLoginInfo(userId, LocalDateTime.now(), loginIp, null);
        return rows > 0;
    }

    @Override
    public boolean validatePassword(String username, String password) {
        return userRepository.findByUsername(username)
                .map(user -> validateEncodedPassword(password, user.getPassword()))
                .orElse(false);
    }

    @Override
    public boolean existsByUsername(String username, Long excludeId) {
        return userRepository.existsByUsername(username, excludeId);
    }

    @Override
    public boolean existsByEmail(String email, Long excludeId) {
        return userRepository.existsByEmail(email, excludeId);
    }

    @Override
    public boolean existsByPhone(String phone, Long excludeId) {
        return userRepository.existsByPhone(phone, excludeId);
    }

    /**
     * 密码加密
     * @param password 原始密码
     * @return 加密后的密码
     */
    private String encodePassword(String password) {
        // TODO: 使用Spring Security的PasswordEncoder
        return password; // 临时返回原密码
    }

    /**
     * 验证密码
     * @param rawPassword 原始密码
     * @param encodedPassword 加密后的密码
     * @return 是否匹配
     */
    private boolean validateEncodedPassword(String rawPassword, String encodedPassword) {
        // TODO: 使用Spring Security的PasswordEncoder验证
        return rawPassword.equals(encodedPassword); // 临时直接比较
    }
}
